import { Global, Logger, Module } from '@nestjs/common'

import { ConfigModule, ConfigService } from '@nestjs/config'
import * as joi from 'joi'
import { LoggerModule } from 'nestjs-pino'
// 1.dotenv方法
import * as dotenv from 'dotenv'
import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm'
import { join } from 'path'
import { connectionParams } from '../ormconfig'
// 模块
import { UserModule } from './user/user.module'
import { RangeModule } from './range/range.module'
import { LogsModule } from './logs/logs.module'
import { AuthModule } from './auth/auth.module'
import { RolesModule } from './roles/roles.module'
import { MenusModule } from './menus/menus.module'
import { APP_GUARD } from '@nestjs/core'
import { AdminGuard } from './guards/admin.guard'
import { ThrottlerGuard, ThrottlerModule } from '@nestjs/throttler'
//如果NODE_ENV存在则用NODE_ENV的值，如果不存在默认为development(开发者)
const envFilePath = `.env.${process.env.NODE_ENV || `development`}`
// development：开发   production：生产

// 2.yaml方法
// 导入yaml配置文件
// import configuration from './configuration'
@Global()
@Module({
  imports: [
    //用于集中管理和加载应用程序的配置，确保应用程序在不同环境中的一致性
    ConfigModule.forRoot({
      isGlobal: true,
      // 1.dotenv方法
      // 指定将要加载环境文件的路径
      envFilePath: envFilePath,
      load: [() => dotenv.config({ path: '.env' })],
      // 环境变量验证模式：joi
      validationSchema: joi.object({
        NODE_ENV: joi.string().valid('development', 'production', 'test').default('development'),
        db_TYPE: joi.string().valid('mysql', 'postgres'),
        // 改动处1：alternatives().try() 的作用是允许同时匹配多种类型,domain(): 限制域名
        db_HOST: joi.alternatives().try(joi.string().ip(), joi.string().domain()),
        db_PORT: joi.number().default(3306),
        db_USERNAME: joi.string().required(),
        db_PASSWORD: joi.string().required(),
        db_DATABASE: joi.string().required(),
        db_SYNC: joi.boolean().default(false),
        LOG_ON: joi.boolean(),
        LOG_LEVEL: joi.string()
      })
      // // 2.yaml方法
      // load: [configuration]
    }),
    // 配置typeorm：一个用于 TypeScript 和 JavaScript 的 ORM（对象关系映射）库，旨在简化与数据库的交互
    TypeOrmModule.forRoot(connectionParams),
    // TypeOrmModule.forRootAsync({
    //   imports: [ConfigModule],
    //   inject: [ConfigService], //注入配置服务
    //   useFactory: (configService: ConfigService) =>
    //     ({
    //       type: configService.get(ConfigEnum.db_TYPE),
    //       host: configService.get(ConfigEnum.db_HOST),
    //       port: configService.get(ConfigEnum.db_PORT),
    //       username: configService.get(ConfigEnum.db_USERNAME),
    //       password: configService.get(ConfigEnum.db_PASSWORD),
    //       database: configService.get(ConfigEnum.db_DATABASE),
    //       // 实体类，实体对象，创建数据库表
    //       entities: [User, Profile, Logs, Roles],
    //       // entities: [Teacher, Score, Student],
    //       // 同步本地的schema与数据库 => 初始化的时候使用
    //       synchronize: configService.get(ConfigEnum.db_SYNC),
    //       // 日志等级
    //       // logging: true//建议在开发环境用
    //       // logging: process.env.NODE_ENV === 'development' //限制在开发环境用
    //       // logging: ['error']
    //       logging: false
    //     }) as TypeOrmModuleOptions
    // }),
    // TypeOrmModule.forRoot({
    //   type: 'mysql',
    //   host: 'localhost',
    //   port: 3306,
    //   username: 'root',
    //   password: '123456',
    //   database: 'test_db',
    //   entities: [],
    //   // 同步本地的schema与数据库 => 初始化的时候使用
    //   synchronize: true,
    //   // 日志等级
    //   logging: ['error']
    // }),
    //
    // 配置第三方日志库：nestjs-pino
    // forRoot() 用于配置和初始化日志功能，并将其作为全局模块集成到应用中。
    LoggerModule.forRoot({
      // pinoHttp: 这个配置项是 Pino HTTP 中间件的配置，允许你定制与 HTTP 请求相关的日志记录行为，
      pinoHttp: {
        // transport 配置项指定日志的输出格式（例如，漂亮的、彩色的输出）和日志记录的级别。
        transport:
          process.env.NODE_ENV === 'development'
            ? {
                level: 'info', //设置日志记录的级别为 info,记录 info、warn、error 级别的,但不会记录 debug 或 trace 级别的日志
                target: 'pino-pretty', //决定了如何格式化和输出日志的工具或模块。
                options: {
                  //用于定制 target值 输出的配置选项
                  colorize: true //是否为日志添加颜色
                }
              }
            : {
                level: 'info', //设置日志记录的级别为 info,记录 info、warn、error 级别的,但不会记录 debug 或 trace 级别的日志
                target: 'pino-roll', //决定了如何格式化和输出日志的工具或模块。
                options: {
                  //用于定制 target值 输出的配置选项
                  file: join('logs', 'logs.txt'),
                  frequency: 'daily',
                  size: '0.1k',
                  mkdir: true
                }
              }
        /*transport: {
          targets: [//指定多个日志输出的目标。它允许将日志信息发送到多个不同的目标，并为每个目标指定不同的配置和处理方式。
            {
              level: 'info', //设置日志记录的级别为 info,记录 info、warn、error 级别的,但不会记录 debug 或 trace 级别的日志
              target: 'pino-pretty', //决定了如何格式化和输出日志的工具或模块。
              options: {
                //用于定制 target值 输出的配置选项
                colorize: true //是否为日志添加颜色
              }
            },
            {
              level: 'info', //设置日志记录的级别为 info,记录 info、warn、error 级别的,但不会记录 debug 或 trace 级别的日志
              target: 'pino-roll', //决定了如何格式化和输出日志的工具或模块。
              options: {
                //用于定制 target值 输出的配置选项
                file: join('logs', 'logs.txt'),
                frequency: 'daily',
                size: '0.1k',
                mkdir: true
              }
            }
          ]
        }*/
      }
    }),
    //限制速率
    ThrottlerModule.forRoot({
      throttlers: [
        {
          ttl: 60000, //生存时间，60秒
          limit: 10 //在ttl时间内最大的请求数
        }
      ]
    }),
    UserModule,
    RangeModule,
    RolesModule,
    LogsModule,
    AuthModule,
    MenusModule
  ], //导入的模块
  controllers: [], //控制器
  providers: [
    Logger,
    {
      provide: APP_GUARD,
      useClass: ThrottlerGuard
    }
    // , { provide: APP_GUARD, useClass: AdminGuard }
  ], //供应商:这个属性用于指定该模块中使用的 服务
  exports: [Logger] //导出
})
export class AppModule {}
